package com.charles.seckillsystem.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.charles.seckillapi.domain.SysGood;
import com.charles.seckillcommon.core.constants.CacheConstants;
import com.charles.seckillcommon.core.domain.AjaxResult;
import com.charles.seckillcommon.redis.service.RedisService;
import com.charles.seckillcommon.security.annotation.RolePermit;
import com.charles.seckillsystem.mapper.SysGoodMapper;
import com.charles.seckillsystem.service.SchedulerService;
import com.charles.seckillsystem.service.SysGoodService;
import com.charles.seckillsystem.vo.UserGoodId;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

@RestController
@RequestMapping("/good")
@EnableTransactionManagement
public class SysGoodController {

    public static final Logger logger = LoggerFactory.getLogger(SysGoodController.class);
    
    @Resource
    private SysGoodMapper sysGoodMapper;

    @Resource
    private SysGoodService sysGoodService;

    @Resource
    private SchedulerService schedulerService;
    
    @Autowired
    private RedisService redisService;

    /**
     * 产品列表
     */
    @GetMapping("goodList")
    @RolePermit(values = "admin:common")
    public AjaxResult queryGoodList() {
        return AjaxResult.success(sysGoodMapper.queryGoodList());
    }

    /**
     * 产品信息
     */
    @GetMapping("/getGood/{goodId}")
    @RolePermit(values = "admin:common")
    public AjaxResult getGood(@PathVariable("goodId") Long goodId) {
        SysGood good = (SysGood) redisService.getCacheObject(CacheConstants.GOOD_ID + goodId);
        if (good == null) {
            good = sysGoodMapper.getGood(goodId);
        }
        return AjaxResult.success(good);
    }

    /**
     * 秒杀产品
     */
    @PostMapping("seckill")
    @SentinelResource(value = "seckillGood", blockHandler = "seckillGoodBlockHandler", fallback = "seckillGoodFallback")
    @RolePermit(values = "admin:common")
    public AjaxResult seckill(@RequestBody UserGoodId userGoodId) {
        return AjaxResult.success(sysGoodService.seckillGood(userGoodId.getUser_id(), userGoodId.getGood_id()));
    }

    /**
     * 开启任务调度
     */
    @PostConstruct
    public void taskInit() throws SchedulerException {
        schedulerService.startDailyJob();
    }

    /**
     * sentinel限流
     * 参数需要与方法一致
     * @param userGoodId
     * @param ex
     * @return
     */
    public AjaxResult seckillGoodBlockHandler(UserGoodId userGoodId, BlockException ex) {
        logger.error("seckillGoodBlockHandler: " + ex.getMessage());
        return AjaxResult.error("请求过于频繁，请稍后再试");
    }

    /**
     * sentinel熔断
     * 参数需要与方法一致
     * @param userGoodId
     * @param throwable
     * @return
     */
    public AjaxResult seckillGoodFallback(UserGoodId userGoodId, Throwable throwable) {
        logger.error("seckillGoodFallback: " + throwable.getMessage());
        return AjaxResult.error(throwable.getMessage());
    }

}
